<template>
	<el-dialog
		title="图片裁剪"
		class="cheng-dialog"
		v-model="dialogVisible"
		:close-on-click-modal="false"
		destroy-on-close
		width="800px"
	>
		<div class="cropper-top">
			<div class="cropper_left">
				<div class="cropper-content">
					<div class="cropper" style="text-align: center">
						<VueCropper
							:style="{ width: '440px' }"
							ref="cropper"
							:img="option.img"
							:outputSize="option.size"
							:outputType="option.outputType"
							:info="true"
							:full="option.full"
							:canMove="option.canMove"
							:canMoveBox="canMoveBox"
							:original="option.original"
							:autoCrop="option.autoCrop"
							:fixed="fixed"
							:fixedNumber="fixedNumber"
							:centerBox="option.centerBox"
							:infoTrue="option.infoTrue"
							:fixedBox="fixedBox"
							:autoCropWidth="autoCropWidth"
							:autoCropHeight="autoCropHeight"
							:enlarge="option.enlarge"
							@cropMoving="cropMoving"
							@realTime="realTime"
						/>
					</div>
				</div>
				<div class="action-box">
					<el-upload
						class="upload-demo"
						action=""
						:auto-upload="false"
						:show-file-list="false"
						:on-change="handleChangeUpload"
					>
						<el-button type="primary" size="mini">更换图片</el-button>
					</el-upload>
					<el-button style="margin-left: 12px" type="primary" size="mini" @click="rotateLeftHandle">
						向左旋转
					</el-button>
					<el-button type="primary" size="mini" @click="rotateRightHandle">向右旋转</el-button>
					<el-button type="primary" size="mini" @click="changeScaleHandle(1)">放大</el-button>
					<el-button type="primary" size="mini" @click="changeScaleHandle(-1)">缩小</el-button>
				</div>
				<!-- <el-button type="primary" plain @click="clearImgHandle">清除图片</el-button> -->
				<!-- <el-button type="primary" plain @click="downloadHandle('blob')">下载</el-button> -->
			</div>
			<div class="cropper_right" v-if="round">
				<div class="preview_text">预览</div>
				<div :style="getStyle" class="previewImg">
					<div :style="previewFileStyle">
						<img :style="previews.img" :src="previews.url" alt="" />
					</div>
				</div>
			</div>
			<div class="cropper_right" v-else>
				<div class="preview_text">预览</div>
				<div :style="getStyle" class="previewImg">
					<div :style="previewFileStyle">
						<img :style="previews.img" :src="previews.url" alt="" />
					</div>
				</div>
			</div>
		</div>
		<template #footer>
			<div class="dialog-footer">
				<el-button @click="dialogVisible = false">取 消</el-button>
				<el-button type="primary" @click="finish" :loading="loading">确认</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script setup>
import { ElMessage, ElMessageBox } from "element-plus"
const props = defineProps({
	autoCropWidth: {
		type: Number,
		default: 200,
	},
	autoCropHeight: {
		type: Number,
		default: 200,
	},
	fixedBox: {
		type: Boolean,
		default: false,
	},
	fixed: {
		type: Boolean,
		default: true,
	},
	round: {
		type: Boolean,
		default: false,
	},
	previewWidth: {
		type: Number,
		default: 150,
	},
	fixedNumber: {
		type: Array,
		default: () => [1, 1],
	},
	outputType: {
		type: String,
		default: "png",
	},
	title: {
		type: String,
		default: "",
	},
	size: {
		type: Number,
		default: 3,
	},
	canMoveBox: {
		type: Boolean,
		default: true,
	},
	mode: {
		type: String,
		default: "contain",
	},
	maxImgSize: {
		type: Number,
		default: 2000,
	},
	enlarge: {
		type: Number,
		default: 1,
	},
	centerBox: {
		type: Boolean,
		default: true,
	},
})
const emits = defineEmits(["update:modelValue", "success"])
const fileUploadUrl = ref("/system/oss/upload")

const isPreview = ref(false)
const dialogVisible = ref(false)
const previewImg = ref("") // 预览图片地址
// 裁剪组件的基础配置option
const option = reactive({
	img: "https://pic1.zhimg.com/80/v2-366c0aeae2b4050fa2fcbfc09c74aad4_720w.jpg", // 裁剪图片的地址
	info: true, // 裁剪框的大小信息
	outputSize: 1, // 裁剪生成图片的质量
	outputType: props.outputType, // 裁剪生成图片的格式
	canScale: true, // 图片是否允许滚轮缩放
	autoCrop: true, // 是否默认生成截图框
	canMoveBox: props.canMoveBox, // 截图框能否拖动
	canMove: true, // 上传图片是否可以移动
	autoCropWidth: props.autoCropWidth, // 默认生成截图框宽度
	autoCropHeight: props.autoCropHeight, // 默认生成截图框高度
	fixedBox: props.fixedBox, // 固定截图框大小 不允许改变
	fixed: props.fixed, // 是否开启截图框宽高固定比例
	fixedNumber: props.fixedNumber, // 截图框的宽高比例
	full: false, // 是否输出原图比例的截图,不失真
	original: false, // 上传图片按照原始比例渲染
	centerBox: props.centerBox, // 截图框是否被限制在图片里面
	infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
	mode: props.mode, // 图片默认渲染方式
	maxImgSize: props.maxImgSize, // 上传图片最大宽度和高度
	enlarge: props.enlarge, // 图片根据截图框输出比例倍数
})
// 防止重复提交
const loading = ref(false)
const fileinfo = ref({})
const previews = ref({})
const previewFileStyle = ref({})
const getStyle = ref({ width: "", height: "" })
const tempScale = ref(0)

const cropper = ref("")

// 上传按钮 限制图片大小和类型
function handleChangeUpload(file) {
	fileinfo.value = file // 保存下当前文件的一些基本信息
	let isJPG = file.raw.type === "image/jpeg" || file.raw.type === "image/png"
	let isLtnM = file.size / 1024 / 1024 < props.size
	if (!isJPG) {
		// this.$message.error("上传头像图片只能是 JPG/PNG 格式!")
		ElMessage.error(`上传${props.title}仅支持 JPG/PNG 格式 ！`)
		return false
	}
	if (!isLtnM) {
		// this.$message.error(`上传头像图片大小不能超过 ${props.size}MB!`)
		ElMessage.error(`上传${props.title}大小不能超过 ${props.size}MB!`)
		return false
	}
	// 上传成功后将图片地址赋值给裁剪框显示图片
	nextTick(async () => {
		// base64方式
		// this.option.img = await fileByBase64(file.raw)
		option.img = URL.createObjectURL(file.raw)
		dialogVisible.value = true
		loading.value = false
	})
}
// 放大/缩小
function changeScaleHandle(num) {
	num = num || 1
	cropper.value.changeScale(num)
}
// 左旋转
function rotateLeftHandle() {
	cropper.value.rotateLeft()
}
// 右旋转
function rotateRightHandle() {
	cropper.value.rotateRight()
}

// 清理图片
function clearImgHandle() {
	option.img = ""
}
// 截图框移动回调函数
function realTime(data) {
	previews.value = data // 预览img图片
	tempScale.value = props.previewWidth / data.w
	previewFileStyle.value = {
		"width": data.w + "px",
		"height": data.h + "px",
		"margin": 0,
		"overflow": "hidden",
		"zoom": tempScale.value,
		"position": "relative",
		"border": "1px solid #e8e8e8",
		"border-radius": props.round ? "50%" : "10px",
	}
}
function finish() {
	// 获取截图的 blob 数据
	cropper.value.getCropBlob(async blob => {
		loading.value = true
		previewImg.value = URL.createObjectURL(blob)
		isPreview.value = true

		// 注此时的data是一个Blob数据，部分接口接收的是File转化的FormData数据
		let formData = new FormData()
		formData.append(
			"upfile",
			new File(
				[blob], // 将Blob类型转化成File类型
				fileinfo.value.name, // 设置File类型的文件名称
				{ type: fileinfo.value.type } // 设置File类型的文件类型
			)
		)
		formData.append("width", props.autoCropWidth)
		formData.append("height", props.autoCropHeight)
		try {
			const data = await postAxios(fileUploadUrl.value, formData)
			emits("success", data)
			dialogVisible.value = false
			loading.value = false
		} catch (error) {
			loading.value = false
			console.log(error)
		}
	})
}

defineExpose({
	handleChangeUpload,
})
</script>

<style lang="scss" scoped>
.cropper-content {
	.cropper {
		width: auto;
		height: 350px;
		// ::v-deep .cropper-view-box {
		// 	border-radius: 50%;
		// }
	}
}
.action-box {
	margin-top: 5px;
	padding: 0 30px;
	width: 100%;
	display: flex;
	justify-content: center;
	.upload-demo {
		margin-right: auto;
	}
	// margin-top: 30px;
}
.dialog-footer {
	display: flex;
	justify-content: flex-end;
}
.cropper-top {
	// overflow: hidden;
	display: flex;
	justify-content: center;
	.cropper_left {
		width: calc(100% - 150px);
		display: flex;
		flex-direction: column;
		align-items: center;
	}
	.cropper_right {
		width: 200px;
		flex: 1;
		margin-left: 44px;
		.preview_text {
			margin-bottom: 12px;
		}
	}
}
.cheng-dialog {
	// width: 700px !important;
}
</style>
